package aceim.protocol.snuk182.xmpp.common; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.jivesoftware.smack.RosterEntry; import org.jivesoftware.smack.RosterGroup; import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.packet.Message; import org.jivesoftware.smack.packet.Presence; import org.jivesoftware.smack.packet.Presence.Mode; import org.jivesoftware.smack.packet.Presence.Type; import org.jivesoftware.smack.packet.RosterPacket; import org.jivesoftware.smack.util.StringUtils; import org.jivesoftware.smackx.Form; import org.jivesoftware.smackx.FormField; import org.jivesoftware.smackx.FormField.Option; import org.jivesoftware.smackx.MessageEventManager; import org.jivesoftware.smackx.muc.HostedRoom; import org.jivesoftware.smackx.muc.MultiUserChat; import org.jivesoftware.smackx.muc.Occupant; import org.jivesoftware.smackx.muc.RoomInfo; import aceim.api.dataentity.Buddy; import aceim.api.dataentity.BuddyGroup; import aceim.api.dataentity.InputFormFeature; import aceim.api.dataentity.MultiChatRoom; import aceim.api.dataentity.OnlineInfo; import aceim.api.dataentity.PersonalInfo; import aceim.api.dataentity.ProtocolServiceFeatureTarget; import aceim.api.dataentity.TextMessage; import aceim.api.dataentity.tkv.ListTKV; import aceim.api.dataentity.tkv.StringTKV; import aceim.api.dataentity.tkv.StringTKV.ContentType; import aceim.api.dataentity.tkv.TKV; import aceim.api.dataentity.tkv.ToggleTKV; import aceim.api.service.ApiConstants; import aceim.api.utils.Logger; import aceim.api.utils.Logger.LoggerLevel; import android.content.Context; import android.text.TextUtils; public class XMPPEntityAdapter { static final byte INVISIBLE_STATUS_ID = 5; private static final Mode[] presenceModes = {Mode.available, Mode.away, Mode.xa, Mode.dnd, Mode.chat}; public TextMessage xmppMessage2TextMessage(Message message, XMPPServiceInternal service, boolean resourceAsWriterId){ if (message == null){ return null; } TextMessage txtMessage; if (resourceAsWriterId){ txtMessage = new TextMessage(service.getOnlineInfo().getServiceId(), StringUtils.parseBareAddress(message.getFrom())); txtMessage.setContactDetail(StringUtils.parseResource(message.getFrom())); } else { String from = normalizeJID(message.getFrom()); txtMessage = new TextMessage(service.getOnlineInfo().getServiceId(), from); } txtMessage.setMessageId(message.getPacketID() != null ? message.getPacketID().hashCode() : message.hashCode()); txtMessage.setTime(System.currentTimeMillis()); txtMessage.setText(message.getBody()); txtMessage.setIncoming(true); return txtMessage; } public Presence userStatus2XMPPPresence(Byte status) { Presence presence; if (status < 0 || status >= presenceModes.length) { presence = new Presence(Type.unavailable); } else { presence = new Presence(Type.available); presence.setMode(presenceModes[status]); } return presence; } public byte xmppPresence2UserStatus(Presence presence) { if (presence == null || presence.getType() != Type.available){ return -1; } if (presence.getMode() == null || presence.getMode() == Mode.available){ return 0; } for (byte i=0; i<presenceModes.length; i++) { Mode m = presenceModes[i]; if (m == presence.getMode()){ return i; } } return -1; } public OnlineInfo presence2OnlineInfo(Presence presence, Context context, byte serviceId, String ownerJid, OnlineInfo onlineInfo){ if (presence == null){ return null; } String jid = normalizeJID(presence.getFrom()); OnlineInfo info; if (onlineInfo != null && jid.equals(onlineInfo.getProtocolUid())) { info = onlineInfo; } else { info = new OnlineInfo(serviceId, jid); } String resource = StringUtils.parseResource(presence.getFrom()); if (!TextUtils.isEmpty(resource)) { info.getFeatures().putString(ApiConstants.FEATURE_BUDDY_RESOURCE, resource); } info.getFeatures().putByte(ApiConstants.FEATURE_STATUS, xmppPresence2UserStatus(presence)); info.setXstatusName(presence.getStatus()); info.getFeatures().putBoolean(ApiConstants.FEATURE_FILE_TRANSFER, true); return info; } public String normalizeJID(String jid){ return StringUtils.parseBareAddress(jid); } public String getClientId(String jid){ if (jid == null){ return null; } if (jid.indexOf("/")>-1){ return jid.split("/")[1]; } return jid; } public Buddy rosterEntry2Buddy(RosterEntry entry, String ownerJid, Context context, byte serviceId){ if (entry == null){ return null; } Buddy buddy = new Buddy(normalizeJID(entry.getUser()), ownerJid, XMPPApiConstants.PROTOCOL_NAME, serviceId); buddy.setName(entry.getName()); buddy.setId(entry.getUser().hashCode()); buddy.setGroupId((entry.getGroups() != null && entry.getGroups().size() > 0) ? entry.getGroups().iterator().next().getName() : ApiConstants.NO_GROUP_ID); //buddy.clientId = getClientId(entry.getUser()); if (entry.getStatus()!=null && entry.getStatus().equals(RosterPacket.ItemStatus.SUBSCRIPTION_PENDING)){ //buddy.visibility = Buddy.VIS_NOT_AUTHORIZED; } return buddy; } public BuddyGroup rosterGroup2BuddyGroup(RosterGroup entry, Collection<RosterEntry> buddies, String ownerUid, Context context, byte serviceId){ if (entry == null){ return null; } BuddyGroup group = new BuddyGroup(entry.getName(), ownerUid, serviceId); group.setName(entry.getName()); for (RosterEntry buddy: entry.getEntries()){ buddies.remove(buddy); group.getBuddyList().add(rosterEntry2Buddy(buddy, ownerUid, context, serviceId)); } return group; } public List<BuddyGroup> rosterGroupCollection2BuddyGroupList(Collection<RosterGroup> entries, Collection<RosterEntry> buddies, String ownerUid, Context context, byte serviceId){ if (entries == null){ return null; } List<RosterEntry> list = new ArrayList<RosterEntry>(buddies); List<BuddyGroup> groups = new ArrayList<BuddyGroup>(entries.size()); for (RosterGroup entry: entries){ groups.add(rosterGroup2BuddyGroup(entry, list, ownerUid, context, serviceId)); } BuddyGroup noGroup = new BuddyGroup(ApiConstants.NO_GROUP_ID, ownerUid, serviceId); for (RosterEntry buddyWithNoGroup : list) { noGroup.getBuddyList().add(rosterEntry2Buddy(buddyWithNoGroup, ownerUid, context, serviceId)); } groups.add(noGroup); return groups; } public List<PersonalInfo> xmppHostedRooms2MultiChatRooms(Collection<HostedRoom> hostedRooms, String ownerJid, byte serviceId) { if (hostedRooms == null){ return Collections.emptyList(); } List<PersonalInfo> chats = new ArrayList<PersonalInfo>(hostedRooms.size()); for (HostedRoom room: hostedRooms){ chats.add(xmppHostedRoom2PersonalInfo(room, serviceId)); } return chats; } private PersonalInfo xmppHostedRoom2PersonalInfo(HostedRoom room, byte serviceId) { if (room == null) { return null; } PersonalInfo info = new PersonalInfo(serviceId); info.setProtocolUid(room.getJid()); info.setMultichat(true); info.getProperties().putString(PersonalInfo.INFO_NICK, room.getName()); return info; } public MultiChatRoom xmppHostedRoom2MultiChatRoom(HostedRoom room, String ownerJid, byte serviceId) { MultiChatRoom chat = new MultiChatRoom(room.getJid(), ownerJid, XMPPApiConstants.PROTOCOL_NAME, serviceId); chat.setName(room.getName()); return chat; } public MultiChatRoom xmppRoomInfo2MultiChatRoom(RoomInfo info, String ownerJid, byte serviceId) { MultiChatRoom chat = new MultiChatRoom(info.getRoom(), ownerJid, XMPPApiConstants.PROTOCOL_NAME, serviceId); chat.setName(info.getDescription()); return chat; } public MultiChatRoom chatRoomInfo2Buddy(RoomInfo info, String ownerJid, byte serviceId, boolean joined) { MultiChatRoom chat = new MultiChatRoom(info.getRoom(), ownerJid, XMPPApiConstants.PROTOCOL_NAME, serviceId); chat.setName((info.getSubject()!= null && info.getSubject().length() > 0) ? info.getSubject() : info.getRoom()); chat.getOnlineInfo().setXstatusName(info.getDescription()); chat.setId(chat.getProtocolUid().hashCode()); if (joined){ chat.getOnlineInfo().getFeatures().putByte(ApiConstants.FEATURE_STATUS, (byte) 0); } return chat; } public MultiChatRoom chatInfo2Buddy(String chatId, String chatName, String ownerJid, byte serviceId, boolean joined) { MultiChatRoom chat = new MultiChatRoom(chatId, ownerJid, XMPPApiConstants.PROTOCOL_NAME, serviceId); chat.setName(chatName); chat.setId(chat.getProtocolUid().hashCode()); if (joined){ chat.getOnlineInfo().getFeatures().putByte(ApiConstants.FEATURE_STATUS, (byte) 0); } return chat; } public Message textMessage2XMPPMessage(TextMessage textMessage, String thread, String to, Message.Type messageType) throws Exception { Message message = new Message(to, messageType); message.setThread(thread); message.setPacketID(textMessage.getMessageId() + ""); MessageEventManager.addNotificationsRequests(message, true, true, true, true); message.setBody(textMessage.getText()); return message; } public List<BuddyGroup> xmppMUCOccupants2mcrOccupants(XMPPServiceInternal service, MultiUserChat muc, boolean loadIcons) { List<BuddyGroup> groups = new ArrayList<BuddyGroup>(); String ownerJid = service.getOnlineInfo().getProtocolUid(); BuddyGroup moderators = new BuddyGroup(Integer.toString(2), ownerJid, service.getOnlineInfo().getServiceId()); BuddyGroup participants = new BuddyGroup(Integer.toString(5), ownerJid, service.getOnlineInfo().getServiceId()); BuddyGroup other = new BuddyGroup(Integer.toString(7), ownerJid, service.getOnlineInfo().getServiceId()); BuddyGroup all = new BuddyGroup(Integer.toString(8), ownerJid, service.getOnlineInfo().getServiceId()); //TODO moderators.setName("Moderators"); participants.setName("Participants"); other.setName("Other"); all.setName("All"); Map<String, Buddy> buddies = new HashMap<String, Buddy>(); Iterator<String> it = muc.getOccupants(); for (;it.hasNext();){ String occupant = it.next(); String buddyId; Occupant occu = muc.getOccupant(occupant); if (occu != null && occu.getJid() != null){ buddyId = normalizeJID(occu.getJid()); if (loadIcons){ try { service.loadCard(buddyId); } catch (Exception e) { Logger.log(e); } } } else { buddyId = occupant; } Buddy buddy = new Buddy(buddyId, ownerJid, XMPPApiConstants.PROTOCOL_NAME, service.getOnlineInfo().getServiceId()); buddy.setName(buddyId.equals(occupant) ? StringUtils.parseResource(occupant) : occu.getNick()); buddy.getOnlineInfo().getFeatures().putByte(ApiConstants.FEATURE_STATUS, xmppPresence2UserStatus(muc.getOccupantPresence(occupant))); buddies.put(buddy.getProtocolUid(), buddy); buddy.setId(buddyId.hashCode()); all.getBuddyList().add(buddy); } try { fillMUCGroup(muc.getParticipants(), participants, buddies); fillMUCGroup(muc.getModerators(), moderators, buddies); other.getBuddyList().addAll(buddies.values()); groups.add(moderators); groups.add(participants); groups.add(other); } catch (Exception e1) { Logger.log(e1); } if (groups.size() < 1){ groups.add(all); } return groups; } private void fillMUCGroup(Collection<Occupant> occupants, BuddyGroup group, Map<String, Buddy> map) { for (Occupant occu : occupants){ String occupantJid = normalizeJID(occu.getJid()); Buddy occupant = map.remove(occupantJid); if (occupant != null) { group.getBuddyList().add(occupant); } } } public RosterEntry buddy2RosterEntry(XMPPConnection connection, Buddy buddy) { return connection.getRoster().getEntry(buddy.getProtocolUid()); } public RosterGroup buddyGroup2RosterEntry(XMPPConnection connection, BuddyGroup buddyGroup) { for (RosterGroup group: connection.getRoster().getGroups()){ if (group.getName().equals(buddyGroup.getId())){ return group; } } return null; } public void addGroupChats(List<BuddyGroup> groups, List<MultiChatRoom> joinedChatRooms, String ownerUid, byte serviceId) { BuddyGroup noGroup = null; for (BuddyGroup g: groups) { if (g.getId().equals(ApiConstants.NO_GROUP_ID)) { noGroup = g; break; } } if (noGroup == null) { noGroup = new BuddyGroup(ApiConstants.NO_GROUP_ID, ownerUid, serviceId); } noGroup.getBuddyList().addAll(joinedChatRooms); } public InputFormFeature chatRoomConfigurationForm2InputFormFeature(Form form, Context context) { if (form == null) { return null; } List<TKV> tkvs = new ArrayList<TKV>(); for (Iterator<FormField> fieldIterator = form.getFields(); fieldIterator.hasNext();){ FormField field = fieldIterator.next(); String type = field.getType(); TKV tkv = null; if (type.equalsIgnoreCase(FormField.TYPE_TEXT_SINGLE) || type.equalsIgnoreCase(FormField.TYPE_TEXT_MULTI) || type.equalsIgnoreCase(FormField.TYPE_JID_SINGLE) || type.equalsIgnoreCase(FormField.TYPE_JID_MULTI)) { tkv = new StringTKV(ContentType.STRING, field.getLabel(), field.isRequired(), null); } else if (type.equalsIgnoreCase(FormField.TYPE_TEXT_PRIVATE)) { tkv = new StringTKV(ContentType.PASSWORD, field.getLabel(), field.isRequired(), null); } else if (type.equalsIgnoreCase(FormField.TYPE_LIST_SINGLE) || type.equalsIgnoreCase(FormField.TYPE_LIST_MULTI)) { tkv = new ListTKV(chatFormListItemChoices2ListTkvChoices(field.getOptions()), field.getLabel(), field.isRequired(), null); } else if (type.equalsIgnoreCase(FormField.TYPE_BOOLEAN)) { tkv = new ToggleTKV(field.getLabel(), field.isRequired(), Boolean.parseBoolean(field.getVariable())); } else { Logger.log("Unsupportable field type: " + type + "/" + field.getLabel(), LoggerLevel.INFO); } if (tkv != null) { tkvs.add(tkv); } } InputFormFeature feature = new InputFormFeature( XMPPApiConstants.FEATURE_CONFIGURE_CHAT_ROOM_RESULT, context.getString(R.string.room_configuration), android.R.drawable.ic_menu_edit, false, false, tkvs.toArray(new TKV[tkvs.size()]), new ProtocolServiceFeatureTarget[]{ProtocolServiceFeatureTarget.BUDDY}); return feature; } private String[] chatFormListItemChoices2ListTkvChoices(Iterator<Option> options) { if (options == null) { return new String[0]; } List<String> list = new ArrayList<String>(); for (;options.hasNext();) { Option o = options.next(); list.add(o.getLabel()); } return list.toArray(new String[list.size()]); } }